package com.zzyl.member.service.Impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import com.zzyl.common.constant.CacheConstants;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.UserThreadLocal;
import com.zzyl.member.domin.Family;
import com.zzyl.member.dto.FamilyDto;
import com.zzyl.member.dto.QueryDevicePropertyStatusDto;
import com.zzyl.member.mapper.FamilyMapper;
import com.zzyl.member.service.FamilyService;
import com.zzyl.member.vo.FamilyMyVo;
import com.zzyl.member.vo.FamilyPage;
import com.zzyl.nursing.domain.Device;
import com.zzyl.nursing.domain.DeviceData;
import com.zzyl.nursing.domain.Elder;
import com.zzyl.nursing.dto.DeviceDto;
import com.zzyl.nursing.service.IDeviceService;
import com.zzyl.nursing.service.IElderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * TODO
 *
 * @Author mr.wu
 * @Date 2025/10/29 19:35
 */
@Service
public class FamilyServiceImpl extends ServiceImpl<FamilyMapper, Family> implements FamilyService {


    @Autowired
    private FamilyMapper familyMapper;
    @Autowired
    private IElderService elderService;
    @Override
    public void add(FamilyDto dto) {
        Long userId = UserThreadLocal.getUserId();
        Elder elder = elderService.lambdaQuery().eq(Elder::getIdCardNo,dto.getIdCard())
                .eq(Elder::getName, dto.getName())
                .one();
        if (elder == null) {
            throw new BaseException("查不到老人信息，请验证身份信息");
        }

        Family family = BeanUtil.toBean(dto, Family.class);
        family.setFamilyMemberId(userId);
        family.setElderId(elder.getId());
        save(family);
    }

    /**
     * 查询家人列表
     * @return
     */
    @Override
    public List<FamilyMyVo> selectMyFamily() {
        Long userId = UserThreadLocal.getUserId();
        List<FamilyMyVo> t = familyMapper.selectMyFamily(userId);
        return t;
    }

    /**
     * 查看家人列表（分页查询）
     *
     * @return
     */
    @Override
    public List<FamilyPage> listByPage(Integer page, Integer pageSize) {
        Long userId = UserThreadLocal.getUserId();
        PageHelper.startPage(page, pageSize);
        List<FamilyPage> list =familyMapper.selectByPage(userId);
        Page<FamilyPage> pageList= (Page<FamilyPage>) list;
        return pageList.getResult();
    }
    /**
     * 查询健康数据
     *
     * @param deviceName
     * @param propertyName
     * @return
     */

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private IoTDAClient client;
    @Autowired
    private IDeviceService  deviceService;
    @Override
    public Map<String, Object> queryDevicePropertyStatus(DeviceDto dto) {

        //根据产品Id和设备名查询设备ID
        Device device = deviceService.lambdaQuery().eq(Device::getProductKey, dto.getProductKey()).eq(Device::getDeviceName, dto.getDeviceName()).one();

        if(device==null){
            throw new BaseException("没有此设备");
        }

        String deviceData = (String)redisTemplate.opsForHash().get(CacheConstants.IOT_DEVICE_DATA_LATEST, device.getIotId());

        List<DeviceData> deviceDataList = JSONUtil.toList(deviceData, DeviceData.class);

        this.moveHeartRateToFourth(deviceDataList);

        List<Map<String,Object>> list = new ArrayList<>();

        deviceDataList.forEach((x)->{
            LocalDateTime alarmTime = x.getAlarmTime();
            String dataValue = x.getDataValue();
            long epochMilli =alarmTime
                    .atZone(ZoneId.of("Asia/Shanghai"))
                    .toInstant().toEpochMilli();
            Map<String,Object> map = new HashMap<>();
            map.put("identifier",x.getFunctionId());
            map.put("time",epochMilli);
            map.put("value",x.getDataValue());
            list.add(map);
        });
        Map<String,Object> propertyStatusInfo = new HashMap<>();
        propertyStatusInfo.put("propertyStatusInfo", list);

        Map<String,Object> result = new HashMap<>();
        result.put("list",propertyStatusInfo);
        return result;
    }

    private  void moveHeartRateToFourth(List<DeviceData> list) {
        int heartRateIndex = -1;
        //获取HeartRate索引
        for (int i = 0; i < list.size(); i++) {
            if ("HeartRate".equalsIgnoreCase(list.get(i).getFunctionId())) {
                heartRateIndex = i;
                break;
            }
        }
        //删除后会返回数据，获取当前heartRateData
        DeviceData heartRateData = list.remove(heartRateIndex);
        //如果长度不为4，那么就放在最后。如果大于等于4，放在索引3位置
        int targetIndex = Math.min(3, list.size());
        list.add(targetIndex, heartRateData);
    }


    /**
     * 按天统计查询指标数据
     *
     * @param dto
     * @return
     */
    @Override
    public List<Map<String, Object>> queryDeviceDataListByDay(QueryDevicePropertyStatusDto dto) {
        //获取设备在所需要的时间范围内的数据，所有的，并且分开，求平均值，封装数据
        LocalDateTime startTime = Instant.ofEpochMilli(dto.getStartTime()).atZone(ZoneId.of("Asia/Shanghai")).toLocalDateTime();
        LocalDateTime endTime = Instant.ofEpochMilli(dto.getEndTime()).atZone(ZoneId.of("Asia/Shanghai")).toLocalDateTime();

        List<Map<String,Object>> list  = familyMapper.queryDeviceDataListByDay(
                startTime,endTime,dto.getIotId(),dto.getFunctionId()
        );

        // 将数据库结果转成 Map<小时, 数据值>
        Map<Integer, Double> dbMap = list.stream()
                .collect(Collectors.toMap(
                        map -> Integer.parseInt(map.get("dateTime").toString()), // 0-23
                        map -> Double.parseDouble(map.get("dataValue").toString())
                ));
    // 遍历每小时，补齐没有的数据
        List<Map<String, Object>> result = new ArrayList<>();
        LocalDateTime tempTime = startTime;
        while (!tempTime.isAfter(endTime)) {
            int hour = tempTime.getHour();
            Map<String, Object> hourData = new HashMap<>();
            hourData.put("dateTime", String.format("%02d:00", hour)); // 格式化 00:00
            hourData.put("dataValue", dbMap.getOrDefault(hour, 0.0));
            result.add(hourData);
            tempTime = tempTime.plusHours(1); // 下一小时
        }
        return result;
    }

    /**
     * 按周统计查询指标数据
     *
     * @param dto
     * @return
     */
    @Override
    public List<Map<String, Object>> queryDeviceDataListByWeek(QueryDevicePropertyStatusDto dto) {
        LocalDateTime startTime = Instant.ofEpochMilli(dto.getStartTime()).atZone(ZoneId.of("Asia/Shanghai")).toLocalDateTime();
        LocalDateTime endTime = Instant.ofEpochMilli(dto.getEndTime()).atZone(ZoneId.of("Asia/Shanghai")).toLocalDateTime();

        List<Map<String,Object>> list  = familyMapper.queryDeviceDataListByWeek(
                startTime,endTime,dto.getIotId(),dto.getFunctionId()
        );



        // 转成 Map<"MM.dd", int>
        Map<String, Integer> collect = list.stream()
                .collect(Collectors.toMap(
                        map -> map.get("dateTime").toString(),
                        map -> ((Number) map.get("dataValue")).intValue()
                ));

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM.dd");

        // 用 Stream 生成结果
        List<Map<String, Object>> result = Stream.iterate(startTime, dt -> dt.plusDays(1))
                .takeWhile(dt -> !dt.isAfter(endTime))
                .map(dt -> {
                    Map<String, Object> dayData = new HashMap<>();
                    String key = dt.format(formatter);
                    dayData.put("dateTime", key);
                    dayData.put("dataValue", collect.getOrDefault(key, 0));
                    return dayData;
                })
                .collect(Collectors.toList());
        return result;
    }

    /**
     * 解除绑定
     *
     * @param id
     */
    @Override
    public void deleteById(Integer id) {
        this.removeById(id);
    }
}
